package com.adopapa.nezhacloud.ddd.codegen;

import java.io.File;
import java.io.FileOutputStream;
import java.io.StringWriter;
import java.util.Properties;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class VelocityUtil {

	private static Logger logger = LoggerFactory.getLogger(VelocityUtil.class);

	/**
	 * 初始化vm方法
	 */
	public static void initVelocity() {
		Properties p = new Properties();
		try {
			// 加载classpath目录下的vm文件
			p.setProperty("resource.loader.file.class",
					"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
			// 定义字符集
			p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
			// 初始化Velocity引擎，指定配置Properties
			Velocity.init(p);
		} catch (Exception e) {
			logger.error(ExceptionUtils.getStackTrace(e));
			throw new RuntimeException(e);
		}
	}

	public static <T> String getFileName(Class<T> clazz, String basePackageName, String templateName) {
//		String filePath = System.getProperty("user.dir") + File.separator + "src" + File.separator ;
//		filePath = filePath + "main" +  File.separator + "java" +  File.separator;
//		filePath = filePath + basePackageName.replaceAll("\\.", "/") + "/service";
//		System.getProperty("user.dir").replaceAll("\\.", "/")
		String url = clazz.getResource("/").getPath().replace("/target/classes/", "").substring(1);
		String filePath = String.format("%s/%s/%s", url, "src/main/java",
				basePackageName.replaceAll("\\.", "/"));
		if ("vm/repository.java.vm".equals(templateName)) {
			filePath = String.format("%s/domain/%sRepository.java", filePath, clazz.getSimpleName());
		} else if ("vm/service.java.vm".equals(templateName)) {
			filePath = String.format("%s/service/%sService.java", filePath, clazz.getSimpleName());
		} else if ("vm/controller.java.vm".equals(templateName)) {
			filePath = String.format("%s/controller/%sController.java", filePath, clazz.getSimpleName());
		} else if ("vm/infos.vue.vm".equals(templateName)) {
			filePath = String.format("%s/vue/%ss.vue", filePath, GenCodeUtil.getCamelName(clazz.getSimpleName()));
		} else if ("vm/info.vue.vm".equals(templateName)) {
			filePath = String.format("%s/vue/%s.vue", filePath, GenCodeUtil.getCamelName(clazz.getSimpleName()));
		}

		return filePath;
	}

	// vm/service.java.vm
	// com.adopapa.origin
	public static <T> void genCode(Class<T> clazz, String projectName, String templateName, String basePackageName) throws Exception {
		// 输出
		String codes = genCodestr(clazz, projectName, templateName, basePackageName);

		String fileName = getFileName(clazz, basePackageName, templateName);

		FileOutputStream os = new FileOutputStream(new File(fileName));
		os.write(codes.getBytes("UTF-8"));
		os.flush();
		os.close();
		
		System.out.println(String.format("%s code is generated", fileName));

	}

	public static <T> String genCodestr(Class<T> clazz, String projectName, String templateName,
			String basePackageName) {
		VelocityEngine engine = new VelocityEngine();
		engine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
		engine.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
		engine.init();
		// 获取模板文件
		Template template = engine.getTemplate(templateName);
		// 设置变量
		VelocityContext ctx = new VelocityContext();
		ctx.put("packageName", basePackageName);
		ctx.put("ClassName", clazz.getSimpleName());
		ctx.put("snakename", GenCodeUtil.camel2Snake(clazz.getSimpleName()));
		ctx.put("projectname", projectName);
		ctx.put("classname", clazz.getSimpleName().toLowerCase());
		ctx.put("className", GenCodeUtil.getCamelName(clazz.getSimpleName()));
		ctx.put("queryFields", GenCodeUtil.getQueryFieldMap(clazz));
		ctx.put("formFields", GenCodeUtil.getFormFieldMap(clazz));
		
		// 输出
		StringWriter sw = new StringWriter();
		template.merge(ctx, sw);
		
		return sw.toString();
	}

}
